function MSTreeViewElement(label) {

    /**
    * TreeElement base css class name prefix.
    *
    * @private
    * @property cssPrefix
    * @type     String
    * @default  messWindowShrinkButton
    */
    this.cssPrefix = "TreeViewElement";

    /**
    * Collection of child TreeViewElement controls
    *
    * @private
    * @property  controls
    * @type      List
    * @default   empty list
    */
    this.controls = new List();

    /**
    * Tree element label
    *
    * @private
    * @property  label
    * @type      String
    * @default   'element'
    */
    this.label = "element";
    if (MSTreeViewElement.arguments.length === 1) {
        this.label = MSTreeViewElement.arguments[0];
    }

    /**
    * Expanded/Shrinked state flag,
    *
    * @private
    * @property  state
    * @type      Boolean
    * @default   true  (expanded state)
    */
    this.state = true;

    /**
    * Reference to header DOM object
    *
    * @private
    * @property  headerDom
    * @type      DOM
    * @default   null
    */
    this.headerDom = null;

    /**
    * Reference to shrink/expand box DOM object
    *
    * @private
    * @property  boxDom
    * @type      DOM
    * @default   null
    */
    this.boxDom = null;

    /**
    * Reference to tree element image DOM object
    *
    * @private
    * @property  imageDom
    * @type      DOM
    * @default   null
    */
    this.imageDom = null;

    /**
    * Reference to tree element descriptive label
    *
    * @private
    * @property  labelDom
    * @type      DOM
    * @default   null
    */
    this.labelDom = null;

    /**
    * Reference to container dom element, where child TreeViewElements will be rendered
    *
    * @private
    * @property  contentDom
    * @type      DOM
    * @default   null
    */
    this.contentDom = null;

    /**
    * Path to theme images.
    *
    * @private
    * @property  IMG_PATH
    * @type      String
    * @default   null
    */

    /**
    * Optional node description
    *
    * @private
    * @property  nodeDescription
    * @type      {String}
    * @default   null
    */
    this.nodeDescription = null;


    this.IMG_PATH = null;

    /** CONSTANTS **/
    this.LEAF = "leaf.gif";
    this.LEAF_OVER = "leafOver.gif"

    this.NODE = "node.gif";
    this.NODE_OVER = "nodeOver.gif";
    this.NODE_EXPANDED = "nodeExpanded.gif";
    this.NODE_EXPANDED_OVER = "nodeExpandedOver.gif";

    this.BOX = "box.gif";
    this.BOX_OVER = "boxOver.gif";
    this.BOX_EXPANDED = "boxExpanded.gif";
    this.BOX_EXPANDED_OVER = "boxExpandedOver.gif";
    this.BOX_EMPTY = "boxEmpty.gif";

    this.NODE_LABEL = "Label";
    this.NODE_LABEL_OVER = this.NODE_LABEL + "Over";

}
MSTreeViewElement.prototype = new MessUIElement();
MessUIElement.prototype.addTagMapping("treeElement", "MSTreeViewElement");




    /**
    * Builds MSTreeViewElement control
    *
    * @public
    * @method  build
    */
    MSTreeViewElement.prototype.build = function() {

        // initialize treeElement object
        this.initControl();
        this.init();
        
        // build dom
        this.buildDOMObject();

        // build child controls (recursive)
        this.buildChildControls();

        // attach event handler
        this.attachEventHandlers();
    };                                  

    /**
    * Attaches event handlers to treeviewelement object. Events are attached to box
    * (shrink/expand) element, image element
    *
    * @private
    * @method  attachEventHandlers  
    */
    MSTreeViewElement.prototype.attachEventHandlers = function() {

        //this.boxDom.addEventListener("")

        // image events
		eventUtil.addEventHandler(this.imageDom, "mouseover", MSTreeViewElement.prototype.imageMouseOverHandler);
		eventUtil.addEventHandler(this.imageDom, "mouseout", MSTreeViewElement.prototype.imageMouseOutHandler);
 
        // box events (mouse movement, shrinkd/expand actions)
        eventUtil.addEventHandler(this.boxDom, "mouseover", MSTreeViewElement.prototype.boxMouseOverHandler);
        eventUtil.addEventHandler(this.boxDom, "mouseout",  MSTreeViewElement.prototype.boxMouseOutHandler);
        eventUtil.addEventHandler(this.boxDom, "mousedown", MSTreeViewElement.prototype.boxMouseDownHandler);

        // label events
        eventUtil.addEventHandler(this.labelDom, "mouseover", MSTreeViewElement.prototype.labelMouseOverHandler);
        eventUtil.addEventHandler(this.labelDom, "mouseout",  MSTreeViewElement.prototype.labelMouseOutHandler);
    };

    /**
    * Image 'mouseover' event handler
    *
    * @event
    * @method   imageMouseOverHandler
    */
    MSTreeViewElement.prototype.imageMouseOverHandler = function() {
		
		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);
        var treeElement = MSTreeViewElement.prototype.objects.get(oSource.id);

        // update display
        if (treeElement.isLeaf()) {
        // leaf node
            treeElement.getImageDom().src = treeElement.IMG_PATH + treeElement.LEAF_OVER;
        }
        else {
        // complex node
            if (treeElement.isShrinked()) {
                treeElement.getImageDom().src = treeElement.IMG_PATH + treeElement.NODE_OVER;
            }
            else if (treeElement.isExpanded()) {
                treeElement.getImageDom().src = treeElement.IMG_PATH + treeElement.NODE_EXPANDED_OVER;
            }
        }
	
		eventUtil.stopEvent(oEvent);
    };

    /**
    * Image 'mouseout' event handler
    *
    * @event
    * @method  imageMouseOutHandler
    */
    MSTreeViewElement.prototype.imageMouseOutHandler = function() {

		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);
        var treeElement = MSTreeViewElement.prototype.objects.get(oSource.id);

        // update display

        if (treeElement.isLeaf()) {
        // leaf node
            treeElement.getImageDom().src = treeElement.IMG_PATH + treeElement.LEAF;
        }
        else {
        // complex node
            if (treeElement.isShrinked()) {
                treeElement.getImageDom().src = treeElement.IMG_PATH + treeElement.NODE;
            }
            else if (treeElement.isExpanded()) {
                treeElement.getImageDom().src = treeElement.IMG_PATH + treeElement.NODE_EXPANDED;
            }
        }

        eventUtil.stopEvent(oEvent);
    };

    /**
    * Box 'mouseover' event handler
    *
    * @event
    * @method  boxMouseOverHandler
    */
    MSTreeViewElement.prototype.boxMouseOverHandler = function() {

		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);
        var treeElement = MSTreeViewElement.prototype.objects.get(oSource.id);

        // update display
        if (!treeElement.isLeaf()) {
            
            if (treeElement.isShrinked()) {
                treeElement.getBoxDom().src = treeElement.IMG_PATH + treeElement.BOX_OVER;
                treeElement.imageMouseOverHandler(oEvent);
            }
            else if (treeElement.isExpanded()) {
                treeElement.getBoxDom().src = treeElement.IMG_PATH + treeElement.BOX_EXPANDED_OVER;
                treeElement.imageMouseOverHandler(oEvent);
            }
        }

        eventUtil.stopEvent(oEvent);
    };

    /**
    * Box 'mouseout' event handler
    *
    * @event
    * @method  boxMouseOutHandler
    */
    MSTreeViewElement.prototype.boxMouseOutHandler = function() {

		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);
        var treeElement = MSTreeViewElement.prototype.objects.get(oSource.id);

        // update display
        if (!treeElement.isLeaf()) {

            if (treeElement.isShrinked()) {
                treeElement.getBoxDom().src = treeElement.IMG_PATH + treeElement.BOX;
                treeElement.imageMouseOutHandler(oEvent);
            }
            else if (treeElement.isExpanded()) {
                treeElement.getBoxDom().src = treeElement.IMG_PATH + treeElement.BOX_EXPANDED;
                treeElement.imageMouseOutHandler(oEvent);
            }
        }

        eventUtil.stopEvent(oEvent);
    };

    /**
    * Box 'mousedown' event handler, triggers shrink/expand actions
    *
    * @event
    * @method  boxMouseDownHandler
    */
    MSTreeViewElement.prototype.boxMouseDownHandler = function() {

        var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);
		var treeElement = MSTreeViewElement.prototype.objects.get(oSource.id);

		if (!treeElement.isLeaf()) {
	        if (treeElement.isShrinked()) {
	        // expand shrinked node
	            treeElement.expand();
	        }
	        else if (treeElement.isExpanded()) {
	        // shrink expanded node
	            treeElement.shrink();
	        }
		}

        eventUtil.stopEvent(oEvent);
    };

    /**
    * Label 'mouseover' event handler
    *
    * @event
    * @method  labelMouseOverHandler
    */
    MSTreeViewElement.prototype.labelMouseOverHandler = function() {
	
		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);
        var treeElement = MSTreeViewElement.prototype.objects.get(oSource.id);

        // update label style
        treeElement.labelDom.className = treeElement.getCssPrefix() + treeElement.NODE_LABEL_OVER;
        // update image display
        treeElement.imageMouseOverHandler(oEvent);
        // update node description
        treeElement.showNodeDescription();

        eventUtil.stopEvent(oEvent);
    };

    /**
    * Label 'mouseout' event handler
    *
    * @event
    * @method  labelMouseOutHandler
    */
    MSTreeViewElement.prototype.labelMouseOutHandler = function() {

		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);
        var treeElement = MSTreeViewElement.prototype.objects.get(oSource.id);

        // update label style
        treeElement.labelDom.className = treeElement.getCssPrefix() + treeElement.NODE_LABEL;
        // update display
        treeElement.imageMouseOutHandler(oEvent);
        // reset node description
        treeElement.showNodeDescription(null);

        eventUtil.stopEvent(oEvent);
    };

    /**
    * Preliminary initializations, used in build method.
    *
    * @private
    * @method  init
    */
    MSTreeViewElement.prototype.init = function() {

        // set path to images directory, using global theme and control theme selector
        this.IMG_PATH = "./style/themes/default/controls/treeview/themes/"+this.getTheme().toLowerCase()+"/img/";
    };

    /**
    * Builds DOM control representation
    *
    * @private
    * @method   buildDOMObject
    */
    MSTreeViewElement.prototype.buildDOMObject = function() {

        var container = DIV();
            container.id = this.id;
            container.className = this.getCssPrefix();

        var headerDiv = DIV();
            headerDiv.id = this.id;
            headerDiv.className = container.className + "Header";
            // save dom reference
            this.headerDom = headerDiv;

            var boxDiv = document.createElement("img");
                boxDiv.id = this.id;
				boxDiv.alt = "";
				boxDiv.border = "0";
				boxDiv.src = this.IMG_PATH + this.BOX;
                if (this.isLeaf()) {
                    boxDiv.src = this.IMG_PATH + this.BOX_EMPTY;
                }
                else if (this.isExpanded()) {
                    boxDiv.src = this.IMG_PATH + this.BOX_EXPANDED; 
                }
                // save dom reference
                this.boxDom = boxDiv;

            var imageDiv = document.createElement("img");
                imageDiv.id = this.id;
				imageDiv.alt = "";
				imageDiv.border = "0";
				imageDiv.src = this.IMG_PATH + this.NODE;
                 if (this.isLeaf()) {
                    imageDiv.src = this.IMG_PATH + this.LEAF;
                }
                else if (this.isExpanded()) {
                    imageDiv.src = this.IMG_PATH + this.NODE_EXPANDED;  
                }
                // save dom reference
                this.imageDom = imageDiv;

            var labelDiv = document.createElement("span");
                labelDiv.id = this.id;
                labelDiv.className = headerDiv.className + "Label";
                labelDiv.appendChild( TEXT(this.label) );
                // save dom reference
                this.labelDom = labelDiv;

        headerDiv.appendChild(boxDiv);
        headerDiv.appendChild(imageDiv);
        headerDiv.appendChild(labelDiv);


        var contentDiv = DIV();
            contentDiv.id = this.id;
            contentDiv.className = container.className + "Content";
            this.contentDom = contentDiv;


        container.appendChild(headerDiv);
        container.appendChild(contentDiv); 

        this.domObject = container;
    };

    /**
    * Builds child controls
    *
    * @private
    * @method   buildChildControls
    */
    MSTreeViewElement.prototype.buildChildControls = function() {

        // build controls
        for (var it = this.controls.iterator(); it.hasNext();) {
            // initialize child control
            this.buildChildControlObject(it.next());
        }

        // sort controls (complex before leaf nodes)
        var complexNodes = new List();
        for (var it = this.controls.iterator(); it.hasNext();) {

            var control = it.next();
            if (control.isComplex()) {
                complexNodes.add(control);
                it.remove();
            }
        }

        // write complex nodes at the start of controls list
        if (!complexNodes.isEmpty()) {
            this.controls.insertAll(0, complexNodes);
        }

        // add controls to content dom container
        for (var it = this.controls.iterator(); it.hasNext();) {
            this.contentDom.appendChild( it.next().render() );
        }
    };

    /**
    * Add child TreeViewElement control to this (parent) control
    *
    * @public
    * @method  addControl
    * @param   {MSTreeViewElement} control   element beeing added
    */
    MSTreeViewElement.prototype.addControl = function(control) {

        control.setParent(this);
        
        if (control.isLeaf()) {
        // adding leaf node
            this.controls.add( control );
        }
        else {
        // if adding control with children structure, add right after last control having child nodes

            var added = false;
            for (var it = this.controls.iterator(); it.hasNext();) {
                if (it.next().isLeaf()) {
                // found leaf node, insert complex node before this leaf node
                    this.controls.insert(it.getIndex(), control);
                    added = true;
                    break;
                }
            }
            if (!added) {
                this.controls.add(control);
            }
        }

        // no logner a leaf node, update this node position in parents controls list
        try {
            this.parent.updateControl(this);
        }catch (ex) {}

        
        return control;
    };

    /**
    * Updates child control. Method called by the child itself. Updates child control position in
    * child collection. (Sorting of complex and leaf nodes)
    *
    * @public
    * @method  updateControl
    * @param   {MSTreeViewElement} control
    */
    MSTreeViewElement.prototype.updateControl = function(control) {

        if (!control.isLeaf()) {
        // updating complex node

            var index = this.controls.indexOf(control);
            if (index !== -1) {
                this.controls.remove(index);
                // find new place for the control in collection
                for (var it = this.controls.iterator(); it.hasNext();) {
                    if (it.next().isLeaf()) {
                        this.controls.insert(it.getIndex(), control);
                        return;
                    }
                }
                // add at the end
                this.controls.add(control);
            }
        }
    };

    /**
    * Shrink tree branch.
    *
    * @public
    * @method  shrink
    */
    MSTreeViewElement.prototype.shrink = function() {

        this.state = false;
        // hide content container
        this.contentDom.style.display = "none";
        // update display of header elements
        this.boxDom.src = this.IMG_PATH + this.BOX;
        this.imageDom.src = this.IMG_PATH + this.NODE;
    };

    /**
    * Expand tree branch.
    *
    * @public
    * @method  expand
    */
    MSTreeViewElement.prototype.expand = function() {

        this.state = true;
        // show content container
        this.contentDom.style.display = "";
        // update display of header elements
        this.boxDom.src = this.IMG_PATH + this.BOX_EXPANDED;
        this.imageDom.src = this.IMG_PATH + this.NODE_EXPANDED;
    };

    /**
    * Set tree element label string
    *
    * @public
    * @method  setLabel
    * @param   {String} label   label to set
    */
    MSTreeViewElement.prototype.setLabel = function(label) {

        this.label = label;
    }

    /**
    * Returns true if tree element is shrinked, false otherwise
    *
    * @public
    * @method  isShrinked
    * @return  {Boolean}  true/false   true if shrinked (state == false)
    */
    MSTreeViewElement.prototype.isShrinked = function() {

        return !this.state;
    };

    /**
    * Returns true if tree element is expanded, false otherwise
    *
    * @public
    * @method  isExpanded
    * @return  {Boolean}  true/false
    */
    MSTreeViewElement.prototype.isExpanded = function() {

        return this.state;
    };

    /**
    * Returns true if this node is a leaf node (no children)
    *
    * @public
    * @method  isLeaf
    * @return  {Boolean} true for leaf nodes, false for branch nodes
    */
    MSTreeViewElement.prototype.isLeaf = function() {

        return this.controls.isEmpty();
    };

    /**
    * Returns true if this node is a complex node (has children)
    *
    * @public
    * @method  isComplex
    * @return  {Boolean}
    */
    MSTreeViewElement.prototype.isComplex = function() {

        return !this.controls.isEmpty();    
    };

    /**
    * Return this.imageDom object
    *
    * @private
    * @method  getImageDom
    * @return  {DOM} imageDom object
    */
    MSTreeViewElement.prototype.getImageDom = function() {

        return this.imageDom;
    };

    /**
    * Return this.boxDom object
    *
    * @private
    * @method  getBoxDom
    * @return  {DOM} boxDom object
    */
    MSTreeViewElement.prototype.getBoxDom = function() {

        return this.boxDom;    
    };

    /**
    * nodeDescription property setter
    *
    * @public
    * @method  setNodeDescription
    * @param   {String}  desc   description to be set
    */
    MSTreeViewElement.prototype.setNodeDescription = function(desc) {

        this.nodeDescription = desc;
    };

    /**
    * Shows node description in parent tree control
    *
    * @public
    * @method   showNodeDescription
    */
    MSTreeViewElement.prototype.showNodeDescription = function() {

        var desc = this.nodeDescription;
        var args = MSTreeViewElement.prototype.showNodeDescription.arguments;
        if (args.length === 1) {
            desc = args[0];
        }

        // okay, find root element and show description
        this.parent.showNodeDescription(desc);
    };



